<!--
 * @Description: 会话
 * @Author: xinqiao lxq1990.0716@qq.com
 * @Date: 2025-03-11
 * @LastEditors: xinqiao lxq1990.0716@qq.com
 * @LastEditTime: 2025-04-29
-->
<script lang="ts" setup>
  import { message } from 'ant-design-vue'
  import { onMounted, onUnmounted, ref } from 'vue'

  import type { IMReceiveMessage } from '/@/components/im'
  import { ConnectStatusEnum, MessageTypeEnum, MsgTypeEnum, useIM } from '/@/components/im'
  import { getPersonData } from '/@/storage'
  import { formatToDateTime } from '/@/utils/date'

  import useMember from './hooks/useMember'
  import useMessage from './hooks/useMessage'
  import { formatDate, getMsgSendOrReceiveType, isMsgReceive, isMsgSend } from './utils'

  const { userId, userName } = getPersonData()

  /** 聊天成员-hook */
  const { members, checkedMember, checkedMemberId, setOnMemberChange, initMembers, addMember, changeMember, searchMemberVal, onSearchMember } = useMember(userId)

  /** 聊天内容-hook */
  const { checkedMessage, initMessage, addMessage, setMessageCheckedMemberId } = useMessage(userId)

  /** im-hook */
  const { connectIM, closeIM, sendTextMsg } = useIM({
    connectConfig: { userId, userName },
    onConnectStatus: (status: ConnectStatusEnum) => onConnectStatus(status),
    onMessage: (msg) => onMessage(msg),
    onError: (err) => onError(err),
  })

  setOnMemberChange(() => {
    setMessageCheckedMemberId(checkedMemberId.value)
    initMessage()
  })

  onMounted(async () => {
    connectIM()
    await initMembers()
    if (members.value?.length > 0) changeMember(members.value[0])
  })

  onUnmounted(() => closeIM())

  /**
   * 监听连接状态
   * @param status 连接状态
   */
  const onConnectStatus = (status: ConnectStatusEnum) => {
    if (status === ConnectStatusEnum.OPEN) console.log('onConnectStatus: ', status, '已连接')
    else if (status === ConnectStatusEnum.CLOSED) console.log('onConnectStatus: ', status, '已关闭')
  }

  /*
   * 监听消息
   * @param res 消息
   */
  const onMessage = (_message: IMReceiveMessage) => {
    console.log('onMessage:', _message)
    let { reqMsg, type } = _message
    if (type !== MessageTypeEnum.CHAT) return
    if (reqMsg.startsWith('pong')) reqMsg = reqMsg.slice(4)
    const reqMsgObj = JSON.parse(reqMsg)
    const isReceive = isMsgReceive(reqMsgObj.recipientId, userId)
    // 接收的消息
    if (isReceive) {
      console.log('onMessage-receive')
      const findedMember = members.value.find((item) => [item.senderId, item.recipientId].includes(reqMsgObj.senderId))
      // 已有成员：添加消息
      if (findedMember) addMessage(reqMsgObj)
      // 新成员：添加成员
      else addMember(reqMsgObj, false)
    }
    // 发送的消息
    else {
      // socket无法监控发出去的消息
      console.log('onMessage-send')
    }
  }

  /** 监听错误 */
  const onError = (err: any) => console.log('onError: ', err)

  /** 聊天输入框值 */
  const inputVal = ref('')

  /** 发送聊天消息 */
  const sendMsg = async () => {
    if (inputVal.value === '') {
      message.error('请输入消息')
      return
    }
    await sendTextMsg({ msg: inputVal.value, toId: checkedMemberId.value as string })
    addMessage({
      msgType: MsgTypeEnum.TEXT_MSG,
      content: inputVal.value,
      headImg: '',
      senderId: userId,
      recipientId: checkedMemberId.value as string,
      userName: checkedMember.value?.userName || '',
      notReceivedCount: 0,
      createdTime: formatToDateTime(new Date()),
    })
    inputVal.value = ''
  }
</script>

<template>
  <div class="chat">
    <div class="title">会话</div>
    <div class="box">
      <div class="member">
        <div class="member-search">
          <a-input-search v-model:value="searchMemberVal" @search="onSearchMember" enter-button placeholder="搜索会话" />
        </div>
        <div class="member-list">
          <div class="member-list-item" :class="{ active: item.checked }" v-for="(item, i) in members" :key="`member-list-item${i}`" @click="changeMember(item)">
            <img class="avatar" :src="item.headImg" />
            <span class="name ellipsis-line-1">{{ item.userName }}</span>
            <span class="time">{{ formatDate(item.createdTime) }}</span>
            <span class="ellipsis-line-1 msg">{{ item.content }}</span>
          </div>
        </div>
      </div>
      <div class="message">
        <div class="message-title">{{ checkedMember?.userName }}</div>
        <div class="message-list">
          <div class="message-list-item" :class="getMsgSendOrReceiveType(item.senderId, userId)" v-for="(item, i) in checkedMessage?.messageItems" :key="`message-list-item${i}`">
            <template v-if="isMsgReceive(item.recipientId, userId)">
              <img class="avatar" :src="item.headImg" />
              <div class="msg">{{ item.content }}</div>
            </template>
            <template v-else-if="isMsgSend(item.senderId, userId)">
              <div class="msg">{{ item.content }}</div>
              <img class="avatar" :src="item.headImg" />
            </template>
          </div>
        </div>
        <div class="message-input">
          <a-textarea class="message-input-textarea" v-model:value="inputVal" @press-enter="sendMsg()" :bordered="false" placeholder="请输入" />
        </div>
      </div>
      <div class="resource">
        <div class="resource-title">用户资料</div>
      </div>
    </div>
  </div>
</template>

<style lang="less" scoped>
  .chat {
    width: 1200px;
    height: 780px;
    border-radius: 10px;
    background: #fff;

    .title {
      height: 60px;
      margin-left: 24px;
      line-height: 60px;
      font-weight: bold;
      font-size: 16px;
      color: #000;
      border-bottom: 1px solid #eee;
    }

    .box {
      display: flex;
      height: 720px;

      .member {
        width: 300px;
        height: 100%;
        border-right: 1px solid #eee;

        .member-search {
          display: flex;
          align-items: center;
          width: 260px;
          height: 60px;
          margin-left: 24px;
        }

        .member-list {
          .member-list-item {
            position: relative;
            height: 70px;
            border-bottom: 1px solid #eee;
            cursor: pointer;

            .avatar {
              position: absolute;
              top: 15px;
              left: 24px;
              width: 40px;
              height: 40px;
              border-radius: 50%;
            }

            .name {
              position: absolute;
              top: 13px;
              left: 74px;
              width: 160px;
              line-height: 20px;
              font-size: 16px;
              color: #000;
            }

            .time {
              position: absolute;
              top: 10px;
              right: 16px;
              line-height: 24px;
              font-size: 12px;
              color: #999;
            }

            .msg {
              position: absolute;
              top: 36px;
              left: 74px;
              width: 210px;
              line-height: 18px;
              font-size: 14px;
              color: #999;
            }

            &.active {
              background: #f6f6f6;
            }
          }
        }
      }

      .message {
        width: 600px;
        height: 100%;
        display: flex;
        flex-direction: column;

        .message-title {
          height: 60px;
          margin-left: 12px;
          line-height: 60px;
          font-size: 16px;
          font-weight: bold;
        }

        .message-list {
          height: calc(100% - 220px);
          padding: 12px 24px;
          overflow: auto;
          background: #f6f6f6;

          .message-list-item {
            display: flex;
            margin-top: 8px;

            .avatar {
              width: 25px;
              height: 25px;
              border-radius: 3px;
            }

            .msg {
              max-width: 315px;
              padding: 5px 10px;
              font-size: 14px;
              line-height: 20px;
              border-radius: 3px;
            }

            &.msg-receive {
              justify-content: flex-start;

              .msg {
                margin-left: 10px;
                background: rgb(91 168 255 / 70%);
              }
            }

            &.msg-send {
              justify-content: flex-end;

              .avatar {
                margin-left: 10px;
              }

              .msg {
                background: rgb(21 220 67 / 70%);
              }
            }
          }
        }

        .message-input {
          height: 160px;

          .message-input-textarea {
            height: 100%;
          }
        }
      }

      .resource {
        width: 300px;
        height: 100%;
        border-left: 1px solid #eee;

        .resource-title {
          height: 60px;
          line-height: 60px;
          padding-left: 12px;
          font-weight: bold;
          border-bottom: 1px solid #eee;
        }
      }
    }
  }
</style>
